<!DOCTYPE html><html lang="zh-CN"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=2"><meta name="theme-color" content="#222"><meta name="generator" content="Hexo 3.9.0"><link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png"><link rel="icon" type="image/png" sizes="32x32" href="/favicon.ico"><link rel="icon" type="image/png" sizes="16x16" href="/favicon.ico"><link rel="mask-icon" href="/images/logo.svg" color="#222"><meta name="baidu-site-verification" content="WIIeufYjj6"><link rel="stylesheet" href="/css/main.css"><link rel="stylesheet" href="/lib/font-awesome/css/font-awesome.min.css"><script id="hexo-configurations">var NexT=window.NexT||{},CONFIG={hostname:new URL("http://winddoing.github.io").hostname,root:"/",scheme:"Mist",version:"7.7.0",exturl:!1,sidebar:{position:"right",width:300,display:"post",padding:18,offset:12,onmobile:!1},copycode:{enable:!0,show_result:!1,style:"flat"},back2top:{enable:!0,sidebar:!1,scrollpercent:!1},bookmark:{enable:!1,color:"#222",save:"auto"},fancybox:!1,mediumzoom:!1,lazyload:!1,pangu:!1,comments:{style:"tabs",active:"livere",storage:!0,lazyload:!1,nav:null,activeClass:"livere"},algolia:{appID:"OWFNL0AG1F",apiKey:"796a4b50e2653330cac4e0f8b1f8ade4",indexName:"winddoing",hits:{per_page:10},labels:{input_placeholder:"输入关键词",hits_empty:"没有找到与「${query}」相关的内容",hits_stats:"${hits} 条相关记录，共耗时 ${time} ms"}},localsearch:{enable:!0,trigger:"auto",top_n_per_article:1,unescape:!1,preload:!1},path:"search.xml",motion:{enable:!0,async:!1,transition:{post_block:"fadeIn",post_header:"slideDownIn",post_body:"slideDownIn",coll_header:"slideLeftIn",sidebar:"slideUpIn"}}}</script><meta name="description" content="Bootloader 是在操作系统运行之前执行的一段小程序。通过这段小程序，我们可以初始化硬件设备、建立内存空间的映射表，从而建立适当的系统软硬件环境，为最终调用操作系统内核做好准备。 uboot引导系统启动, UBoot包含两个阶段的启动，一个是SPL启动，一个是正常的启动我们称为第二阶段Uboot。当然，我们也可以选择使用SPL和不使用，主要根据CPU中的SRAM（或者cache，bootra"><meta name="keywords" content="uboot"><meta property="og:type" content="article"><meta property="og:title" content="uboot"><meta property="og:url" content="http://winddoing.github.io/post/47503.html"><meta property="og:site_name" content="Winddoing&#39;s Blog"><meta property="og:description" content="Bootloader 是在操作系统运行之前执行的一段小程序。通过这段小程序，我们可以初始化硬件设备、建立内存空间的映射表，从而建立适当的系统软硬件环境，为最终调用操作系统内核做好准备。 uboot引导系统启动, UBoot包含两个阶段的启动，一个是SPL启动，一个是正常的启动我们称为第二阶段Uboot。当然，我们也可以选择使用SPL和不使用，主要根据CPU中的SRAM（或者cache，bootra"><meta property="og:locale" content="zh-CN"><meta property="og:image" content="http://winddoing.github.io/images/uboot/uboot_stage.png"><meta property="og:image" content="http://winddoing.github.io/images/uboot/uboot_boot.png"><meta property="og:updated_time" content="2020-07-04T09:34:15.252Z"><meta name="twitter:card" content="summary"><meta name="twitter:title" content="uboot"><meta name="twitter:description" content="Bootloader 是在操作系统运行之前执行的一段小程序。通过这段小程序，我们可以初始化硬件设备、建立内存空间的映射表，从而建立适当的系统软硬件环境，为最终调用操作系统内核做好准备。 uboot引导系统启动, UBoot包含两个阶段的启动，一个是SPL启动，一个是正常的启动我们称为第二阶段Uboot。当然，我们也可以选择使用SPL和不使用，主要根据CPU中的SRAM（或者cache，bootra"><meta name="twitter:image" content="http://winddoing.github.io/images/uboot/uboot_stage.png"><link rel="canonical" href="http://winddoing.github.io/post/47503.html"><script id="page-configurations">CONFIG.page={sidebar:"",isHome:!1,isPost:!0}</script><link rel="stylesheet" href="//cdn.jsdelivr.net/gh/theme-next/theme-next-needmoreshare2@1/needsharebutton.min.css"><style>#needsharebutton-postbottom{cursor:pointer;height:26px;margin-top:10px;position:relative}#needsharebutton-postbottom .btn{border:1px solid $btn-default-border-color;border-radius:3px;display:initial;padding:1px 4px}</style><title>uboot | Winddoing's Blog</title><script>var _hmt=_hmt||[];!function(){var e=document.createElement("script");e.src="https://hm.baidu.com/hm.js?38fa95924670925239ef842cb0c8722b";var t=document.getElementsByTagName("script")[0];t.parentNode.insertBefore(e,t)}()</script><noscript><style>.sidebar-inner,.use-motion .brand,.use-motion .collection-header,.use-motion .comments,.use-motion .menu-item,.use-motion .pagination,.use-motion .post-block,.use-motion .post-body,.use-motion .post-header{opacity:initial}.use-motion .site-subtitle,.use-motion .site-title{opacity:initial;top:initial}.use-motion .logo-line-before i{left:initial}.use-motion .logo-line-after i{right:initial}</style></noscript></head><body itemscope itemtype="http://schema.org/WebPage"><div class="container use-motion"><div class="headband"></div><header class="header" itemscope itemtype="http://schema.org/WPHeader"><div class="header-inner"><div class="site-brand-container"><div class="site-meta"><div><a href="/" class="brand" rel="start"><span class="logo-line-before"><i></i></span> <span class="site-title">Winddoing's Blog</span><span class="logo-line-after"><i></i></span></a></div><h1 class="site-subtitle" itemprop="description">Follow Excellent, Success will Chase you</h1></div><div class="site-nav-toggle"><div class="toggle" aria-label="切换导航栏"><span class="toggle-line toggle-line-first"></span><span class="toggle-line toggle-line-middle"></span><span class="toggle-line toggle-line-last"></span></div></div></div><nav class="site-nav"><ul id="menu" class="menu"><li class="menu-item menu-item-home"><a href="/" rel="section"><i class="fa fa-fw fa-home"></i> 首页</a></li><li class="menu-item menu-item-tags"><a href="/tags/" rel="section"><i class="fa fa-fw fa-tags"></i> 标签</a></li><li class="menu-item menu-item-categories"><a href="/categories/" rel="section"><i class="fa fa-fw fa-th"></i> 分类</a></li><li class="menu-item menu-item-archives"><a href="/archives/" rel="section"><i class="fa fa-fw fa-archive"></i> 归档</a></li><li class="menu-item menu-item-about"><a href="/about/" rel="section"><i class="fa fa-fw fa-user"></i> 关于</a></li><li class="menu-item menu-item-search"><a role="button" class="popup-trigger"><i class="fa fa-search fa-fw"></i> 搜索</a></li></ul></nav><div class="site-search"><div class="popup search-popup"><div class="search-header"><span class="search-icon"><i class="fa fa-search"></i></span><div class="search-input-container"> <input autocomplete="off" autocorrect="off" autocapitalize="none" placeholder="搜索..." spellcheck="false" type="text" id="search-input"></div><span class="popup-btn-close"><i class="fa fa-times-circle"></i></span></div><div id="search-result"></div></div><div class="search-pop-overlay"></div></div></div></header><div class="back-to-top"><i class="fa fa-arrow-up"></i> <span>0%</span></div><main class="main"><div class="main-inner"><div class="content-wrap"><div class="content"><div class="posts-expand"><article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN"><link itemprop="mainEntityOfPage" href="http://winddoing.github.io/post/47503.html"><span hidden itemprop="author" itemscope itemtype="http://schema.org/Person"><meta itemprop="image" content="/images/Winddoing.jpg"><meta itemprop="name" content="Winddoing"><meta itemprop="description" content="失败缘于忽视细处，成功始于重视小事。"></span><span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization"><meta itemprop="name" content="Winddoing's Blog"></span><header class="post-header"><h2 class="post-title" itemprop="name headline"> uboot</h2><div class="post-meta"><span class="post-meta-item"><span class="post-meta-item-icon"><i class="fa fa-calendar-o"></i></span> <span class="post-meta-item-text">发表于</span> <time title="创建时间：2018-03-19 23:07:24" itemprop="dateCreated datePublished" datetime="2018-03-19T23:07:24+08:00">2018-03-19</time></span><span class="post-meta-item"><span class="post-meta-item-icon"><i class="fa fa-folder-o"></i></span> <span class="post-meta-item-text">分类于</span> <span itemprop="about" itemscope itemtype="http://schema.org/Thing"><a href="/categories/uboot/" itemprop="url" rel="index"><span itemprop="name">uboot</span></a></span></span><span id="/post/47503.html" class="post-meta-item leancloud_visitors" data-flag-title="uboot" title="阅读次数"><span class="post-meta-item-icon"><i class="fa fa-eye"></i></span> <span class="post-meta-item-text">阅读次数：</span><span class="leancloud-visitors-count"></span></span><span class="post-meta-item" title="阅读次数" id="busuanzi_container_page_pv" style="display:none"><span class="post-meta-item-icon"><i class="fa fa-eye"></i></span> <span class="post-meta-item-text">阅读次数：</span><span id="busuanzi_value_page_pv"></span></span><br><span class="post-meta-item" title="本文字数"><span class="post-meta-item-icon"><i class="fa fa-file-word-o"></i></span> <span class="post-meta-item-text">本文字数：</span> <span>20k</span></span><span class="post-meta-item" title="阅读时长"><span class="post-meta-item-icon"><i class="fa fa-clock-o"></i></span> <span class="post-meta-item-text">阅读时长 &asymp;</span> <span>18 分钟</span></span></div></header><div class="post-body" itemprop="articleBody"><p>Bootloader 是在操作系统运行之前执行的一段小程序。通过这段小程序，我们可以初始化硬件设备、建立内存空间的映射表，从而建立适当的系统软硬件环境，为最终调用操作系统内核做好准备。</p><p>uboot引导系统启动, UBoot包含两个阶段的启动，一个是SPL启动，一个是正常的启动我们称为第二阶段Uboot。当然，我们也可以选择使用SPL和不使用，主要根据CPU中的SRAM（或者cache，bootram阶段需要初始化完成）的大小，如果不能放下uboot大小，则必须先使用SPL启动，进行DDR的初始化，以获取更大的可以空间。</p><blockquote><p>Version: u-boot-201307</p></blockquote><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">+----------------+-----------------------------------+</span><br><span class="line">|                |                                   |</span><br><span class="line">|  spl           |             uboot                 |</span><br><span class="line">|                |                                   |</span><br><span class="line">+----------------+-----------------------------------+</span><br></pre></td></tr></table></figure><p>在编译的过程中,这两个阶段通过<code>CONFIG_SPL_BUILD</code>宏将编译分离。拥有不同的配置，所以许多地方的宏是和SPL的不一样。而且链接的文件也不一致。</p><ul><li><p>SPL：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">./arch/mips/cpu/xburst/x1000/u-boot-spl.lds</span><br></pre></td></tr></table></figure></li><li><p>uboot：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">/arch/mips/cpu/u-boot.lds</span><br></pre></td></tr></table></figure></li></ul><a id="more"></a><h2 id="目的"><a href="#目的" class="headerlink" title="目的"></a>目的</h2><p><img src="/images/uboot/uboot_stage.png" alt="uboot stage"></p><h2 id="流程"><a href="#流程" class="headerlink" title="流程:"></a>流程:</h2><p><img src="/images/uboot/uboot_boot.png" alt="uboot boot"></p><h2 id="SPL"><a href="#SPL" class="headerlink" title="SPL"></a>SPL</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">u-boot-spl.lds</span><br><span class="line">ENTRY: _start (start.S)</span><br><span class="line">		\-&gt;board_init_f (soc.c)</span><br><span class="line">			-&gt;board_init_r (spl.c)</span><br></pre></td></tr></table></figure><h3 id="u-boot-spl-lds"><a href="#u-boot-spl-lds" class="headerlink" title="u-boot-spl.lds"></a>u-boot-spl.lds</h3><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">define</span> CONFIG_SPL_TEXT_BASE        0xf4001000</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> CONFIG_SPL_MAX_SIZE     (12 * 1024)</span></span><br></pre></td></tr></table></figure><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line">MEMORY &#123; .sram : ORIGIN = CONFIG_SPL_TEXT_BASE,\</span><br><span class="line">		LENGTH = CONFIG_SPL_MAX_SIZE &#125;</span><br><span class="line"></span><br><span class="line">OUTPUT_ARCH(mips)</span><br><span class="line">ENTRY(_start)</span><br><span class="line">SECTIONS</span><br><span class="line">&#123;</span><br><span class="line">	.text      :</span><br><span class="line">	&#123;</span><br><span class="line">		__start = .;</span><br><span class="line">		*(.start_section*)</span><br><span class="line">		*(.text*)</span><br><span class="line">	&#125; &gt;.sram</span><br><span class="line">	...</span><br><span class="line"></span><br><span class="line">	.bss : &#123;</span><br><span class="line">		. = ALIGN(4);</span><br><span class="line">		__bss_start = .;</span><br><span class="line">		*(.sbss.*)</span><br><span class="line">		*(.bss.*)</span><br><span class="line">		*(COMMON)</span><br><span class="line">		. = ALIGN(4);</span><br><span class="line">		__bss_end = .;</span><br><span class="line">	&#125; &gt;.sram</span><br><span class="line">	...</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><blockquote><p><a href="/downloads/uboot/u-boot-spl.lds.txt">u-boot-spl.lds</a></p></blockquote><p>在bootram将SPL搬到静态ram中后，执行SPL的代码将从<code>_start</code>开始。</p><h3 id="start-S"><a href="#start-S" class="headerlink" title="start.S"></a>start.S</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br></pre></td><td class="code"><pre><span class="line">#define RESERVED_FOR_SC(x) .space 1536, x</span><br><span class="line"></span><br><span class="line">	.set noreorder</span><br><span class="line"></span><br><span class="line">	.globl _start</span><br><span class="line">	.section .start_section</span><br><span class="line">_start:</span><br><span class="line">	/* magic value (&quot;MSPL&quot;) */</span><br><span class="line">	.word 0x4d53504c</span><br><span class="line">	.space 508, 0</span><br><span class="line">	RESERVED_FOR_SC(0)</span><br><span class="line"></span><br><span class="line">#ifdef CONFIG_SPL_VERSION</span><br><span class="line">	.word (0x00000000 | CONFIG_SPL_VERSION)</span><br><span class="line">	.space (512-20),0</span><br><span class="line">#else</span><br><span class="line">	.space (512-16),0</span><br><span class="line">#endif</span><br><span class="line"></span><br><span class="line">	/* Invalidate BTB */</span><br><span class="line">	mfc0	v0, CP0_CONFIG, 7</span><br><span class="line">	nop</span><br><span class="line">	ori	v0, v0, 2 /* MMU类型：BAT类型*/</span><br><span class="line">	mtc0	v0, CP0_CONFIG, 7</span><br><span class="line">	nop</span><br><span class="line"></span><br><span class="line">	/*</span><br><span class="line">	 * CU0=UM=EXL=IE=0, BEV=ERL=1, IP2~7=1</span><br><span class="line">	 */</span><br><span class="line">	li	t0, 0x0040FC04</span><br><span class="line">	mtc0	t0, CP0_STATUS</span><br><span class="line"></span><br><span class="line">	/* CAUSE register */</span><br><span class="line">	/* IV=1, use the specical interrupt vector (0x200) */</span><br><span class="line">	li	t1, 0x00800000</span><br><span class="line">	mtc0	t1, CP0_CAUSE</span><br><span class="line"></span><br><span class="line">	.set push</span><br><span class="line">	.set	mips32</span><br><span class="line">init_caches:</span><br><span class="line">	li	t0, CONF_CM_CACHABLE_NONCOHERENT</span><br><span class="line">	mtc0	t0, CP0_CONFIG</span><br><span class="line">	nop</span><br><span class="line"></span><br><span class="line">	/* enable idx-store-data cache insn */</span><br><span class="line">	li      t0, 0x20000000</span><br><span class="line">	mtc0    t0, CP0_ECC</span><br><span class="line"></span><br><span class="line">	li	t1, KSEG0		/* Start address */</span><br><span class="line">#define CACHE_ALLOC_END (CONFIG_SYS_DCACHE_SIZE)</span><br><span class="line"></span><br><span class="line">	ori     t2, t1, CACHE_ALLOC_END	/* End address */</span><br><span class="line">	mtc0	zero, CP0_TAGLO, 0</span><br><span class="line">	mtc0	zero, CP0_TAGLO, 1</span><br><span class="line">cache_clear_a_line:</span><br><span class="line">	cache   INDEX_STORE_TAG_I, 0(t1)</span><br><span class="line">	cache   INDEX_STORE_TAG_D, 0(t1)</span><br><span class="line">	addiu   t1, t1, CONFIG_SYS_CACHELINE_SIZE</span><br><span class="line">	bne     t1, t2, cache_clear_a_line</span><br><span class="line">	nop</span><br><span class="line">	.set pop</span><br><span class="line"></span><br><span class="line">	/* Set up stack */</span><br><span class="line">#ifdef CONFIG_SPL_STACK</span><br><span class="line">	li	sp, CONFIG_SPL_STACK</span><br><span class="line">#endif</span><br><span class="line"></span><br><span class="line">	j	board_init_f</span><br><span class="line">	nop</span><br></pre></td></tr></table></figure><blockquote><p><a href="/downloads/uboot/spl_start.S">start.S</a></p></blockquote><ol><li>设置spl的空间布局,加载识别区域，SC填充区域等</li><li>选择MMU类型</li><li>通过SR，使能异常向量和配置中断屏蔽位</li><li>配置一个特殊的中断异常入口（0x200）</li><li>初始化cache</li><li>跳转<code>board_init_f</code></li></ol><h3 id="soc-c"><a href="#soc-c" class="headerlink" title="soc.c"></a>soc.c</h3><h4 id="数据结构"><a href="#数据结构" class="headerlink" title="数据结构"></a>数据结构</h4><h5 id="bd-t"><a href="#bd-t" class="headerlink" title="bd_t"></a>bd_t</h5><blockquote><p>保存板子参数</p></blockquote><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">typedef</span> <span class="class"><span class="keyword">struct</span> <span class="title">bd_info</span> &#123;</span></span><br><span class="line">    <span class="keyword">unsigned</span> <span class="keyword">int</span>    bi_baudrate;    <span class="comment">/*serial console baudrate*/</span></span><br><span class="line">    <span class="keyword">unsigned</span> <span class="keyword">long</span>   bi_arch_number; <span class="comment">/*unique id for this board*/</span></span><br><span class="line">    <span class="keyword">unsigned</span> <span class="keyword">long</span>   bi_boot_params; <span class="comment">/*where this board expects params*/</span></span><br><span class="line">    <span class="keyword">unsigned</span> <span class="keyword">long</span>   bi_memstart;    <span class="comment">/*start of DRAM memory*/</span></span><br><span class="line">    <span class="keyword">phys_size_t</span> bi_memsize; <span class="comment">/*size  of DRAM memory in bytes*/</span></span><br><span class="line">    <span class="keyword">unsigned</span> <span class="keyword">long</span>   bi_flashstart;  <span class="comment">/*start of FLASH memory*/</span></span><br><span class="line">    <span class="keyword">unsigned</span> <span class="keyword">long</span>   bi_flashsize;   <span class="comment">/*size  of FLASH memory*/</span></span><br><span class="line">    <span class="keyword">unsigned</span> <span class="keyword">long</span>   bi_flashoffset; <span class="comment">/*reserved area for startup monitor*/</span></span><br><span class="line">&#125; <span class="keyword">bd_t</span>;</span><br></pre></td></tr></table></figure><blockquote><p>file: arch/mips/include/asm/u-boot.h</p></blockquote><h5 id="gd-t"><a href="#gd-t" class="headerlink" title="gd_t"></a>gd_t</h5><blockquote><p>全局的系统初始化参数</p></blockquote><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">typedef</span> <span class="class"><span class="keyword">struct</span> <span class="title">global_data</span> &#123;</span></span><br><span class="line">	<span class="keyword">bd_t</span> *bd;</span><br><span class="line">	<span class="keyword">unsigned</span> <span class="keyword">long</span> flags;</span><br><span class="line">	<span class="keyword">unsigned</span> <span class="keyword">int</span> baudrate;</span><br><span class="line">	<span class="keyword">unsigned</span> <span class="keyword">long</span> cpu_clk;	<span class="comment">/* CPU clock in Hz!		*/</span></span><br><span class="line">	<span class="keyword">unsigned</span> <span class="keyword">long</span> bus_clk;</span><br><span class="line">	<span class="comment">/* We cannot bracket this with CONFIG_PCI due to mpc5xxx */</span></span><br><span class="line">	<span class="keyword">unsigned</span> <span class="keyword">long</span> pci_clk;</span><br><span class="line">	<span class="keyword">unsigned</span> <span class="keyword">long</span> mem_clk;</span><br><span class="line"><span class="meta">#<span class="meta-keyword">if</span> defined(CONFIG_LCD) || defined(CONFIG_VIDEO)</span></span><br><span class="line">	<span class="keyword">unsigned</span> <span class="keyword">long</span> fb_base;	<span class="comment">/* Base address of framebuffer mem */</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">endif</span></span></span><br><span class="line">	...</span><br><span class="line"><span class="meta">#<span class="meta-keyword">ifdef</span> CONFIG_BOARD_TYPES</span></span><br><span class="line">	<span class="keyword">unsigned</span> <span class="keyword">long</span> board_type;</span><br><span class="line"><span class="meta">#<span class="meta-keyword">endif</span></span></span><br><span class="line">	<span class="keyword">unsigned</span> <span class="keyword">long</span> have_console;	<span class="comment">/* serial_init() was called */</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">ifdef</span> CONFIG_PRE_CONSOLE_BUFFER</span></span><br><span class="line">	<span class="keyword">unsigned</span> <span class="keyword">long</span> precon_buf_idx;	<span class="comment">/* Pre-Console buffer index */</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">endif</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">ifdef</span> CONFIG_MODEM_SUPPORT</span></span><br><span class="line">	<span class="keyword">unsigned</span> <span class="keyword">long</span> do_mdm_init;</span><br><span class="line">	<span class="keyword">unsigned</span> <span class="keyword">long</span> be_quiet;</span><br><span class="line"><span class="meta">#<span class="meta-keyword">endif</span></span></span><br><span class="line">	<span class="keyword">unsigned</span> <span class="keyword">long</span> env_addr;	<span class="comment">/* Address  of Environment struct */</span></span><br><span class="line">	<span class="keyword">unsigned</span> <span class="keyword">long</span> env_valid;	<span class="comment">/* Checksum of Environment valid? */</span></span><br><span class="line"></span><br><span class="line">	<span class="keyword">unsigned</span> <span class="keyword">long</span> ram_top;	<span class="comment">/* Top address of RAM used by U-Boot */</span></span><br><span class="line"></span><br><span class="line">	<span class="keyword">unsigned</span> <span class="keyword">long</span> relocaddr;	<span class="comment">/* Start address of U-Boot in RAM */</span></span><br><span class="line">	<span class="keyword">phys_size_t</span> ram_size;	<span class="comment">/* RAM size */</span></span><br><span class="line">	<span class="keyword">unsigned</span> <span class="keyword">long</span> mon_len;	<span class="comment">/* monitor len */</span></span><br><span class="line">	<span class="keyword">unsigned</span> <span class="keyword">long</span> irq_sp;		<span class="comment">/* irq stack pointer */</span></span><br><span class="line">	<span class="keyword">unsigned</span> <span class="keyword">long</span> start_addr_sp;	<span class="comment">/* start_addr_stackpointer */</span></span><br><span class="line">	<span class="keyword">unsigned</span> <span class="keyword">long</span> reloc_off;</span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">global_data</span> *<span class="title">new_gd</span>;</span>	<span class="comment">/* relocated global data */</span></span><br><span class="line">	<span class="keyword">const</span> <span class="keyword">void</span> *fdt_blob;	<span class="comment">/* Our device tree, NULL if none */</span></span><br><span class="line">	<span class="keyword">void</span> *new_fdt;		<span class="comment">/* Relocated FDT */</span></span><br><span class="line">	<span class="keyword">unsigned</span> <span class="keyword">long</span> fdt_size;	<span class="comment">/* Space reserved for relocated FDT */</span></span><br><span class="line">	<span class="keyword">void</span> **jt;		<span class="comment">/* jump table */</span></span><br><span class="line">	<span class="keyword">char</span> env_buf[<span class="number">32</span>];	<span class="comment">/* buffer for getenv() before reloc. */</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">ifdef</span> CONFIG_TRACE</span></span><br><span class="line">	<span class="keyword">void</span>		*trace_buff;	<span class="comment">/* The trace buffer */</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">endif</span></span></span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">arch_global_data</span> <span class="title">arch</span>;</span>	<span class="comment">/* architecture-specific data */</span></span><br><span class="line">&#125; <span class="keyword">gd_t</span>;</span><br></pre></td></tr></table></figure><blockquote><p>file: include/asm-generic/global_data.h</p></blockquote><h4 id="board-init-f"><a href="#board-init-f" class="headerlink" title="board_init_f"></a>board_init_f</h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">board_init_f</span><span class="params">(ulong dummy)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	<span class="comment">/*Set global data pointer*/</span></span><br><span class="line">	gd = &amp;gdata;</span><br><span class="line"></span><br><span class="line">	<span class="comment">/*Setup global info*/</span></span><br><span class="line">	gd-&gt;arch.gi = &amp;ginfo;</span><br><span class="line"></span><br><span class="line">	gpio_init();</span><br><span class="line"></span><br><span class="line">	<span class="comment">/*Init uart first*/</span></span><br><span class="line">	enable_uart_clk();</span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">ifdef</span> CONFIG_SPL_SERIAL_SUPPORT</span></span><br><span class="line">	preloader_console_init();</span><br><span class="line"><span class="meta">#<span class="meta-keyword">endif</span></span></span><br><span class="line">	<span class="built_in">printf</span>(<span class="string">"ERROR EPC %x\n"</span>, read_c0_errorepc());</span><br><span class="line"></span><br><span class="line">	debug(<span class="string">"Timer init\n"</span>);</span><br><span class="line">	timer_init();</span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">ifdef</span> CONFIG_SPL_CORE_VOLTAGE</span></span><br><span class="line">	debug(<span class="string">"Set core voltage:%dmv\n"</span>, CONFIG_SPL_CORE_VOLTAGE);</span><br><span class="line">	spl_regulator_set_voltage(REGULATOR_CORE, CONFIG_SPL_CORE_VOLTAGE);</span><br><span class="line"><span class="meta">#<span class="meta-keyword">endif</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">ifdef</span> CONFIG_SPL_MEM_VOLTAGE</span></span><br><span class="line">	debug(<span class="string">"Set mem voltage:%dmv\n"</span>, CONFIG_SPL_MEM_VOLTAGE);</span><br><span class="line">	spl_regulator_set_voltage(REGULATOR_MEM, CONFIG_SPL_MEM_VOLTAGE);</span><br><span class="line"><span class="meta">#<span class="meta-keyword">endif</span></span></span><br><span class="line"></span><br><span class="line">	debug(<span class="string">"CLK stop\n"</span>);</span><br><span class="line">	clk_prepare();</span><br><span class="line"></span><br><span class="line">	debug(<span class="string">"PLL init\n"</span>);</span><br><span class="line">	pll_init();</span><br><span class="line"></span><br><span class="line">	debug(<span class="string">"CLK init\n"</span>);</span><br><span class="line">	clk_init();</span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">ifdef</span> CONFIG_HW_WATCHDOG</span></span><br><span class="line">	debug(<span class="string">"WATCHDOG init\n"</span>);</span><br><span class="line">	hw_watchdog_init();</span><br><span class="line"><span class="meta">#<span class="meta-keyword">endif</span></span></span><br><span class="line">	debug(<span class="string">"SDRAM init\n"</span>);</span><br><span class="line">	sdram_init();</span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">ifdef</span> CONFIG_DDR_TEST</span></span><br><span class="line">	ddr_basic_tests();</span><br><span class="line"><span class="meta">#<span class="meta-keyword">endif</span></span></span><br><span class="line"></span><br><span class="line">	<span class="comment">/*Clear the BSS*/</span></span><br><span class="line">	<span class="built_in">memset</span>(__bss_start, <span class="number">0</span>, (<span class="keyword">char</span> *)&amp;__bss_end - __bss_start);</span><br><span class="line"></span><br><span class="line">	debug(<span class="string">"board_init_r\n"</span>);</span><br><span class="line">	board_init_r(<span class="literal">NULL</span>, <span class="number">0</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><blockquote><p>file: arch/mips/cpu/xburst/x1000/soc.c</p></blockquote><ol><li>初始化GPIO</li><li>使能串口时钟，初始化串口</li><li>初始化timer</li><li>初始化时钟,配置CPU，DDR和外设的时钟大小</li><li>初始化看门狗</li><li>初始化DDR</li><li>清除BSS段</li></ol><h5 id="ginfo"><a href="#ginfo" class="headerlink" title="ginfo"></a>ginfo</h5><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;asm-generic/global_data.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> DECLARE_GLOBAL_DATA_PTR     register volatile gd_t *gd asm (<span class="meta-string">"k0"</span>)</span></span><br><span class="line"></span><br><span class="line">DECLARE_GLOBAL_DATA_PTR;</span><br><span class="line"><span class="keyword">gd_t</span> gdata __attribute__ ((section(<span class="string">".data"</span>)));</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">global_info</span> <span class="title">ginfo</span> __<span class="title">attribute__</span> ((<span class="title">section</span>(".<span class="title">data</span>"))) = &#123;</span></span><br><span class="line">    .extal      = CONFIG_SYS_EXTAL,</span><br><span class="line">    .cpufreq    = CONFIG_SYS_CPU_FREQ,</span><br><span class="line">    .ddrfreq    = CONFIG_SYS_MEM_FREQ,</span><br><span class="line">    .uart_idx   = CONFIG_SYS_UART_INDEX,</span><br><span class="line">    .baud_rate  = CONFIG_BAUDRATE,</span><br><span class="line">	...</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>系统信息的结构体 (gd 是指 Global Data, bd 是指 Board info Data) 应该存放于在 DRAM 控制器未初始化之前就能使用的空间中，比如TCSM中。</p><h5 id="为什么要清除BSS段？"><a href="#为什么要清除BSS段？" class="headerlink" title="为什么要清除BSS段？"></a>为什么要清除BSS段？</h5><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* Clear the BSS */</span></span><br><span class="line"><span class="built_in">memset</span>(__bss_start, <span class="number">0</span>, (<span class="keyword">char</span> *)&amp;__bss_end - __bss_start);</span><br></pre></td></tr></table></figure><blockquote><p>可执行程序包括BSS段、代码段、数据段。BSS（Block Started by Symbol）通常指用来存放程序中未初始化的全局变量和静态变量的一块内存区域，特点是可读可写，在程序执行之前BSS段会自动清0。所以，未初始化的全局变量在程序执行之前已经成0</p></blockquote><p>bss段起源于unix中。变量分两种，<code>全局变量</code>和<code>局部变量</code>。局部变量是保留在栈中的，根据C语言规定，如果对局部变量不进行初始化，初始值是不确定的，在栈中位置也不固定。全局变量有专门的数据段存储，且初始化值为0，且位置是固定的。综上，数据分为俩种，<code>位置固定（全局，数据段）</code>，<code>位置不固定（局部-栈里）</code>。</p><p>其实，数据段里的这么多<code>全局变量都初始化为0存在目标文件中是没有必要的，增大了存储空间使用</code>。所以就把数据段里边数据，也即未初始化全局变量存放到了BSS段里边. 并未占有真正的空间。<code>当有目标文件被载入的时候，清除bss段，将全局变量清0</code>, 其实也是在为bss段分配空间.</p><h4 id="board-init-r"><a href="#board-init-r" class="headerlink" title="board_init_r"></a>board_init_r</h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">board_init_r</span><span class="params">(<span class="keyword">gd_t</span> *dummy1, ulong dummy2)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	u32 boot_device;</span><br><span class="line">	<span class="keyword">char</span> *cmdargs = <span class="literal">NULL</span>;</span><br><span class="line">	debug(<span class="string">"&gt;&gt;spl:board_init_r()\n"</span>);</span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">ifdef</span> CONFIG_SYS_SPL_MALLOC_START</span></span><br><span class="line">	mem_malloc_init(CONFIG_SYS_SPL_MALLOC_START,</span><br><span class="line">			CONFIG_SYS_SPL_MALLOC_SIZE);</span><br><span class="line"><span class="meta">#<span class="meta-keyword">endif</span></span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">ifndef</span> CONFIG_PPC</span></span><br><span class="line">	<span class="comment">/*</span></span><br><span class="line"><span class="comment">	 * timer_init() does not exist on PPC systems. The timer is initialized</span></span><br><span class="line"><span class="comment">	 * and enabled (decrementer) in interrupt_init() here.</span></span><br><span class="line"><span class="comment">	 */</span></span><br><span class="line">	timer_init();</span><br><span class="line"><span class="meta">#<span class="meta-keyword">endif</span></span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">ifdef</span> CONFIG_SPL_BOARD_INIT</span></span><br><span class="line">	spl_board_init();</span><br><span class="line"><span class="meta">#<span class="meta-keyword">endif</span></span></span><br><span class="line">	boot_device = spl_boot_device();</span><br><span class="line">	debug(<span class="string">"boot device - %d\n"</span>, boot_device);</span><br><span class="line"><span class="meta">#<span class="meta-keyword">ifdef</span> CONFIG_PALLADIUM</span></span><br><span class="line">	spl_board_prepare_for_linux();</span><br><span class="line"><span class="meta">#<span class="meta-keyword">endif</span></span></span><br><span class="line">	<span class="keyword">switch</span> (boot_device) &#123;</span><br><span class="line">	<span class="keyword">case</span> BOOT_DEVICE_MMC1:</span><br><span class="line">	<span class="keyword">case</span> BOOT_DEVICE_MMC2:</span><br><span class="line">	<span class="keyword">case</span> BOOT_DEVICE_MMC2_2:</span><br><span class="line">		spl_mmc_load_image();</span><br><span class="line">		<span class="keyword">break</span>;</span><br><span class="line">	...</span><br><span class="line">	<span class="keyword">default</span>:</span><br><span class="line">		debug(<span class="string">"SPL: Un-supported Boot Device\n"</span>);</span><br><span class="line">		hang();</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">	<span class="keyword">switch</span> (spl_image.os) &#123;</span><br><span class="line">	<span class="keyword">case</span> IH_OS_U_BOOT:</span><br><span class="line">		debug(<span class="string">"Jumping to U-Boot\n"</span>);</span><br><span class="line">		<span class="keyword">break</span>;</span><br><span class="line"><span class="meta">#<span class="meta-keyword">ifdef</span> CONFIG_SPL_OS_BOOT</span></span><br><span class="line">	<span class="keyword">case</span> IH_OS_LINUX:</span><br><span class="line">		debug(<span class="string">"Jumping to Linux\n"</span>);</span><br><span class="line">		spl_board_prepare_for_linux();</span><br><span class="line"></span><br><span class="line">		cmdargs = cmdargs ? cmdargs : CONFIG_SYS_SPL_ARGS_ADDR;</span><br><span class="line">		cmdargs = spl_board_process_bootargs(cmdargs);</span><br><span class="line"></span><br><span class="line">		debug(<span class="string">"get cmdargs: %s.\n"</span>, cmdargs);</span><br><span class="line">		jump_to_image_linux((<span class="keyword">void</span> *)cmdargs);</span><br><span class="line"><span class="meta">#<span class="meta-keyword">endif</span></span></span><br><span class="line">	<span class="keyword">default</span>:</span><br><span class="line">		debug(<span class="string">"Unsupported OS image.. Jumping nevertheless..\n"</span>);</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">	jump_to_image_no_args(&amp;spl_image);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><blockquote><p>file: common/spl/spl.c</p></blockquote><ol><li>从存储介质（sd/emmc）读取uboot，并跳转到uboot执行</li><li>在SPL运行完后，已可以直接加载kernel或相应的BIN文件执行</li></ol><h3 id="执行C代码所必需的条件或者环境？"><a href="#执行C代码所必需的条件或者环境？" class="headerlink" title="执行C代码所必需的条件或者环境？"></a>执行C代码所必需的条件或者环境？</h3><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">la  sp, STACK_TOP   <span class="comment">// sp</span></span><br><span class="line">j   main</span><br><span class="line">nop</span><br></pre></td></tr></table></figure><ol><li>禁止看门狗，防止CPU不断的重启</li><li>设置堆栈</li></ol><h3 id="SPL执行阶段其栈空间的位置？"><a href="#SPL执行阶段其栈空间的位置？" class="headerlink" title="SPL执行阶段其栈空间的位置？"></a>SPL执行阶段其栈空间的位置？</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">   TCSM</span><br><span class="line">+-------------+ &lt;-+ 0xb2400000</span><br><span class="line">|  .data .bss |       4K</span><br><span class="line">+----------+--+ &lt;-+ 0xb2401000</span><br><span class="line">|    stack |  |       4K</span><br><span class="line">+----------v--+ &lt;-+ 0xb2402000</span><br><span class="line">|             |</span><br><span class="line">|             |</span><br><span class="line">|             |</span><br><span class="line">|   load spl  |       24KB</span><br><span class="line">|             |</span><br><span class="line">|             |</span><br><span class="line">|             |</span><br><span class="line">|             |</span><br><span class="line">+-------------+ &lt;-+ 0xb2408000</span><br></pre></td></tr></table></figure><p>CPU上电后，在bootrom中执行时，由于其是固化的代码段（只读）。因此在上电初期将Data段，BSS段以及栈指定到TCSM中（一个静态RAM，CPU上电即可以使用）。bootrom中一些外围设备如sd boot的SD控制器等初始化完成后，在SD卡中将SPL加载到TCSM中，bootrom的PC跳入SPL进行执行，此时<strong><em>依然使用bootrom的栈空间</em></strong>。</p><h2 id="uboot"><a href="#uboot" class="headerlink" title="uboot"></a>uboot</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">u-boot.lds</span><br><span class="line">__start （start.S）</span><br><span class="line">	-&gt;board_init_f (arch/mips/lib/board.c)</span><br><span class="line">		-&gt;relocate_code (start.S)</span><br><span class="line">				-&gt;board_init_r (arch/mips/lib/board.c)</span><br></pre></td></tr></table></figure><h3 id="u-boot-lds"><a href="#u-boot-lds" class="headerlink" title="u-boot.lds"></a>u-boot.lds</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line">OUTPUT_ARCH(mips)</span><br><span class="line">ENTRY(_start)</span><br><span class="line">SECTIONS</span><br><span class="line">&#123;</span><br><span class="line">	. = 0x00000000;</span><br><span class="line"></span><br><span class="line">	. = ALIGN(4);</span><br><span class="line">	.text : &#123;</span><br><span class="line">		*(.text*)</span><br><span class="line">	&#125;</span><br><span class="line">	...</span><br><span class="line">	. = ALIGN(4);</span><br><span class="line">	.data : &#123;</span><br><span class="line">		*(.data*)</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">	. = .;</span><br><span class="line">	_gp = ALIGN(16) + 0x7ff0;  /*32KB*/</span><br><span class="line"></span><br><span class="line">	...</span><br></pre></td></tr></table></figure><blockquote><p><a href="/downloads/uboot/u-boot.lds.txt">u-boot.lds</a></p></blockquote><h3 id="start-S-1"><a href="#start-S-1" class="headerlink" title="start.S"></a>start.S</h3><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">define</span> CONFIG_SYS_SDRAM_BASE       0x80000000 <span class="comment">/* cached (KSEG0) address */</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> CONFIG_SYS_INIT_SP_OFFSET   0x400000</span></span><br></pre></td></tr></table></figure><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">.set noreorder</span><br><span class="line"></span><br><span class="line">.globl _start</span><br><span class="line">.text</span><br><span class="line">_start:</span><br><span class="line">/* Initialize $gp */</span><br><span class="line">bal	1f</span><br><span class="line"> nop</span><br><span class="line">.word	_gp</span><br><span class="line">1:</span><br><span class="line">lw	gp, 0(ra)</span><br><span class="line"></span><br><span class="line">/* Set up temporary stack */</span><br><span class="line">li	sp, CONFIG_SYS_SDRAM_BASE + CONFIG_SYS_INIT_SP_OFFSET</span><br><span class="line"></span><br><span class="line">la	t9, board_init_f</span><br><span class="line">jr	t9</span><br><span class="line"> nop</span><br></pre></td></tr></table></figure><blockquote><p><a href="/downloads/uboot/uboot_start.S">start.S</a></p></blockquote><ol><li>重新设置栈指针<code>0x80400000</code>,</li><li>跳转<code>board_init_f</code></li></ol><blockquote><p><code>CONFIG_SYS_SDRAM_BASE ＝ 0x8000 0000</code> ，是 MIPS 虚拟寻址空间中<code>kseg0</code>段的起始地址（参考《 See MIPS Run 》），它经过 CPU TLB 翻译后是 DRAM 内存的起始物理地址。</p></blockquote><h4 id="为什么不直接跳转，而使用jr"><a href="#为什么不直接跳转，而使用jr" class="headerlink" title="为什么不直接跳转，而使用jr"></a>为什么不直接跳转，而使用<code>jr</code></h4><p>这样就可以知道代码的位置,而不是标号值。</p><h3 id="board-c"><a href="#board-c" class="headerlink" title="board.c"></a>board.c</h3><h4 id="uboot内存布局："><a href="#uboot内存布局：" class="headerlink" title="uboot内存布局："></a>uboot内存布局：</h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">define</span> CONFIG_SYS_SDRAM_BASE       0x80000000 <span class="comment">/* cached (KSEG0) address */</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> CONFIG_SYS_SDRAM_MAX_TOP    0x90000000 <span class="comment">/* don't run into IO space */</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> CONFIG_SYS_INIT_SP_OFFSET   0x400000</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> CONFIG_SYS_LOAD_ADDR        0x88000000</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> CONFIG_SYS_MEMTEST_START    0x80000000</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> CONFIG_SYS_MEMTEST_END      0x88000000</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> CONFIG_SYS_TEXT_BASE        0x80100000</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> CONFIG_SYS_MONITOR_BASE     CONFIG_SYS_TEXT_BASE</span></span><br></pre></td></tr></table></figure><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">+-------------------+ &lt;-+ 0x9000 0000</span><br><span class="line">|                   |</span><br><span class="line">|                   |</span><br><span class="line">|                   |</span><br><span class="line">|     LOAD_ADDR     |</span><br><span class="line">|                   |</span><br><span class="line">|                   |</span><br><span class="line">+-------------------+ &lt;-+ 0x8800 0000</span><br><span class="line">|                   |</span><br><span class="line">|                   |</span><br><span class="line">|                   |</span><br><span class="line">|                   |</span><br><span class="line">|                   |</span><br><span class="line">|                   |</span><br><span class="line">+-------------------+ &lt;-+ 0x8040 0000</span><br><span class="line">|                   |</span><br><span class="line">|      STACK        |</span><br><span class="line">|                   |</span><br><span class="line">+-------------------+ &lt;-+ 0x8010 0000</span><br><span class="line">|     TEXT BASE     |</span><br><span class="line">+-------------------+ &lt;-+ 0x8000 0000</span><br></pre></td></tr></table></figure><h4 id="board-init-f-1"><a href="#board-init-f-1" class="headerlink" title="board_init_f"></a>board_init_f</h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">board_init_f</span><span class="params">(ulong bootflag)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	<span class="keyword">gd_t</span> gd_data, *id;</span><br><span class="line">	<span class="keyword">bd_t</span> *bd;</span><br><span class="line">	<span class="keyword">init_fnc_t</span> **init_fnc_ptr;</span><br><span class="line">	ulong addr, addr_sp, len;</span><br><span class="line">	ulong *s;</span><br><span class="line"></span><br><span class="line">	<span class="comment">/* Pointer is writable since we allocated a register for it.</span></span><br><span class="line"><span class="comment">	 */</span></span><br><span class="line">	gd = &amp;gd_data;</span><br><span class="line">	<span class="comment">/* compiler optimization barrier needed for GCC &gt;= 3.4 */</span></span><br><span class="line">	__asm__ __volatile__(<span class="string">""</span> : : : <span class="string">"memory"</span>);</span><br><span class="line"></span><br><span class="line">	<span class="built_in">memset</span>((<span class="keyword">void</span> *)gd, <span class="number">0</span>, <span class="keyword">sizeof</span>(<span class="keyword">gd_t</span>));</span><br><span class="line"></span><br><span class="line">	<span class="keyword">for</span> (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) &#123;</span><br><span class="line">		<span class="keyword">if</span> ((*init_fnc_ptr)() != <span class="number">0</span>)</span><br><span class="line">			hang();</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">	<span class="comment">/*</span></span><br><span class="line"><span class="comment">	 * Now that we have DRAM mapped and working, we can</span></span><br><span class="line"><span class="comment">	 * relocate the code and continue running from DRAM.</span></span><br><span class="line"><span class="comment">	 */</span></span><br><span class="line">	addr = CONFIG_SYS_SDRAM_BASE + gd-&gt;ram_size;</span><br><span class="line"><span class="meta">#<span class="meta-keyword">ifdef</span> CONFIG_SYS_SDRAM_MAX_TOP</span></span><br><span class="line">	addr = MIN(addr, CONFIG_SYS_SDRAM_MAX_TOP);</span><br><span class="line"><span class="meta">#<span class="meta-keyword">endif</span></span></span><br><span class="line"></span><br><span class="line">	<span class="comment">/* We can reserve some RAM "on top" here.</span></span><br><span class="line"><span class="comment">	 */</span></span><br><span class="line"></span><br><span class="line">	<span class="comment">/* round down to next 4 kB limit.</span></span><br><span class="line"><span class="comment">	 */</span></span><br><span class="line">	addr &amp;= ~(<span class="number">4096</span> - <span class="number">1</span>);	<span class="comment">//addr &amp;= ~0x0FFF 这种计算是常用的地址对齐，向下 4K 字节对齐</span></span><br><span class="line">	<span class="built_in">printf</span>(<span class="string">"Top of RAM usable for U-Boot at: %08lx\n"</span>, addr);</span><br><span class="line"><span class="meta">#<span class="meta-keyword">ifdef</span> CONFIG_LCD</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">ifdef</span> CONFIG_FB_ADDR</span></span><br><span class="line">	gd-&gt;fb_base = CONFIG_FB_ADDR;</span><br><span class="line"><span class="meta">#<span class="meta-keyword">else</span></span></span><br><span class="line">	<span class="comment">/* reserve memory for LCD display (always full pages) */</span></span><br><span class="line">	addr = lcd_setmem(addr);</span><br><span class="line">	<span class="built_in">printf</span>(<span class="string">"Reserving %ldk for LCDC at: %08lx\n"</span>, len &gt;&gt; <span class="number">10</span>, addr);</span><br><span class="line">	gd-&gt;fb_base = addr;</span><br><span class="line"><span class="meta">#<span class="meta-keyword">endif</span> <span class="comment">/* CONFIG_FB_ADDR */</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">endif</span> <span class="comment">/* CONFIG_LCD */</span></span></span><br><span class="line"></span><br><span class="line">	<span class="comment">/* Reserve memory for U-Boot code, data &amp; bss</span></span><br><span class="line"><span class="comment">	 * round down to next 16 kB limit</span></span><br><span class="line"><span class="comment">	 */</span></span><br><span class="line">	len = bss_end() - CONFIG_SYS_MONITOR_BASE;</span><br><span class="line">	addr -= len;</span><br><span class="line">	addr &amp;= ~(<span class="number">16</span> * <span class="number">1024</span> - <span class="number">1</span>); <span class="comment">// 向下 64K 字节对齐</span></span><br><span class="line"></span><br><span class="line">	<span class="built_in">printf</span>(<span class="string">"Reserving %ldk for U-Boot at: %08lx\n"</span>, len &gt;&gt; <span class="number">10</span>, addr);</span><br><span class="line"></span><br><span class="line">	 <span class="comment">/* Reserve memory for malloc() arena.</span></span><br><span class="line"><span class="comment">	 */</span></span><br><span class="line">	addr_sp = addr - TOTAL_MALLOC_LEN;	<span class="comment">// 划分 malloc() 使用的空间，即所谓的堆空间</span></span><br><span class="line">	<span class="built_in">printf</span>(<span class="string">"Reserving %dk for malloc() at: %08lx\n"</span>,</span><br><span class="line">			TOTAL_MALLOC_LEN &gt;&gt; <span class="number">10</span>, addr_sp);</span><br><span class="line"></span><br><span class="line">	<span class="comment">/*</span></span><br><span class="line"><span class="comment">	 * (permanently) allocate a Board Info struct</span></span><br><span class="line"><span class="comment">	 * and a permanent copy of the "global" data</span></span><br><span class="line"><span class="comment">	 */</span></span><br><span class="line">	addr_sp -= <span class="keyword">sizeof</span>(<span class="keyword">bd_t</span>);</span><br><span class="line">	bd = (<span class="keyword">bd_t</span> *)addr_sp;</span><br><span class="line">	gd-&gt;bd = bd;</span><br><span class="line">	<span class="built_in">printf</span>(<span class="string">"Reserving %zu Bytes for Board Info at: %08lx\n"</span>,</span><br><span class="line">			<span class="keyword">sizeof</span>(<span class="keyword">bd_t</span>), addr_sp);</span><br><span class="line"></span><br><span class="line">	addr_sp -= <span class="keyword">sizeof</span>(<span class="keyword">gd_t</span>);</span><br><span class="line">	id = (<span class="keyword">gd_t</span> *)addr_sp;</span><br><span class="line">	<span class="built_in">printf</span>(<span class="string">"Reserving %zu Bytes for Global Data at: %08lx\n"</span>,</span><br><span class="line">			<span class="keyword">sizeof</span>(<span class="keyword">gd_t</span>), addr_sp);</span><br><span class="line"></span><br><span class="line">	<span class="comment">/* Reserve memory for boot params.</span></span><br><span class="line"><span class="comment">	 */</span></span><br><span class="line">	addr_sp -= CONFIG_SYS_BOOTPARAMS_LEN;</span><br><span class="line">	bd-&gt;bi_boot_params = addr_sp;</span><br><span class="line">	<span class="built_in">printf</span>(<span class="string">"Reserving %dk for boot params() at: %08lx\n"</span>,</span><br><span class="line">			CONFIG_SYS_BOOTPARAMS_LEN &gt;&gt; <span class="number">10</span>, addr_sp);</span><br><span class="line"></span><br><span class="line">	<span class="comment">/*</span></span><br><span class="line"><span class="comment">	 * Finally, we set up a new (bigger) stack.</span></span><br><span class="line"><span class="comment">	 *</span></span><br><span class="line"><span class="comment">	 * Leave some safety gap for SP, force alignment on 16 byte boundary</span></span><br><span class="line"><span class="comment">	 * Clear initial stack frame</span></span><br><span class="line"><span class="comment">	 */</span></span><br><span class="line">	addr_sp -= <span class="number">16</span>;</span><br><span class="line">	addr_sp &amp;= ~<span class="number">0xF</span>; <span class="comment">// 栈空间 16 字节对齐</span></span><br><span class="line">	s = (ulong *)addr_sp;</span><br><span class="line">	*s-- = <span class="number">0</span>;</span><br><span class="line">	*s-- = <span class="number">0</span>;</span><br><span class="line">	addr_sp = (ulong)s;</span><br><span class="line">	<span class="built_in">printf</span>(<span class="string">"Stack Pointer at: %08lx\n"</span>, addr_sp);</span><br><span class="line"></span><br><span class="line">	<span class="comment">/*</span></span><br><span class="line"><span class="comment">	 * Save local variables to board info struct</span></span><br><span class="line"><span class="comment">	 */</span></span><br><span class="line">	bd-&gt;bi_memstart	= CONFIG_SYS_SDRAM_BASE;	<span class="comment">/* start of DRAM */</span></span><br><span class="line">	bd-&gt;bi_memsize	= gd-&gt;ram_size;		<span class="comment">/* size of DRAM in bytes */</span></span><br><span class="line">	bd-&gt;bi_baudrate	= gd-&gt;baudrate;		<span class="comment">/* Console Baudrate */</span></span><br><span class="line"></span><br><span class="line">	<span class="comment">// 将在临时栈空间中的 GD 数据拷贝入 DRAM 中，至此， BD 和 GD 都已经存在于 DRAM 中了</span></span><br><span class="line">	<span class="built_in">memcpy</span>(id, (<span class="keyword">void</span> *)gd, <span class="keyword">sizeof</span>(<span class="keyword">gd_t</span>));</span><br><span class="line"></span><br><span class="line">	relocate_code(addr_sp, id, addr);</span><br><span class="line"></span><br><span class="line">	<span class="comment">/*NOTREACHED - relocate_code() does not return*/</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><ul><li>调用init_sequence 函数队列，对板子进行一些初始化</li></ul><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment"> * initialization sequence configurable to the user.</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * The requirements for any new initalization function is simple: it</span></span><br><span class="line"><span class="comment"> * receives a pointer to the "global data" structure as it's only</span></span><br><span class="line"><span class="comment"> * argument, and returns an integer return code, where 0 means</span></span><br><span class="line"><span class="comment"> * "continue" and != 0 means "fatal error, hang the system".</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="function"><span class="keyword">typedef</span> <span class="title">int</span> <span class="params">(<span class="keyword">init_fnc_t</span>)</span><span class="params">(<span class="keyword">void</span>)</span></span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">init_fnc_t</span> *init_sequence[] = &#123;</span><br><span class="line">	 board_early_init_f,</span><br><span class="line">	 timer_init,</span><br><span class="line">	 env_init,		<span class="comment">/* initialize environment */</span></span><br><span class="line">#ifdef CONFIG_INCA_IP</span><br><span class="line">	 incaip_set_cpuclk,	<span class="comment">/* set cpu clock according to env. variable */</span></span><br><span class="line">#endif</span><br><span class="line">	 init_baudrate,		<span class="comment">/* initialize baudrate settings */</span></span><br><span class="line">	 serial_init,		<span class="comment">/* serial communications setup */</span></span><br><span class="line">	 console_init_f,</span><br><span class="line">	 display_banner,		<span class="comment">/* say that we are here */</span></span><br><span class="line">	 checkboard,</span><br><span class="line">	 init_func_ram,</span><br><span class="line">	 <span class="literal">NULL</span>,</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure><ul><li>为uboot在DRAM中执行准备条件</li></ul><h4 id="relocate-code"><a href="#relocate-code" class="headerlink" title="relocate_code"></a>relocate_code</h4><p>重定位，U-boot运行后将自己的代码段,数据段,BSS 段等搬到DRAM 中的另一个位置继续运行.</p><p><strong>目的：</strong></p><ol><li>为kernel腾出内存的低端空间，防止kernel解压覆盖uboot。</li><li>对于由静态存储器（spiflash nandflash）启动，这个relocation是必须的，将代码搬到DRAM中运行</li></ol><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">relocate_code(addr_sp, id, addr);</span><br></pre></td></tr></table></figure><blockquote><p>id: 之前在 U-boot 的 1M 空间中分配的 GD 结构体的地址<br>addr: U-boot 重新定位到 DRAM 之后的代码起始地址</p></blockquote><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br></pre></td><td class="code"><pre><span class="line">/*</span><br><span class="line"> * void relocate_code (addr_sp, gd, addr_moni)</span><br><span class="line"> *</span><br><span class="line"> * This &quot;function&quot; does not return, instead it continues in RAM</span><br><span class="line"> * after relocating the monitor code.</span><br><span class="line"> *</span><br><span class="line"> * a0 = addr_sp</span><br><span class="line"> * a1 = gd</span><br><span class="line"> * a2 = destination address</span><br><span class="line"> */</span><br><span class="line">	.globl	relocate_code</span><br><span class="line">	.ent	relocate_code</span><br><span class="line">relocate_code:</span><br><span class="line">	move	sp, a0			# set new stack pointer</span><br><span class="line"></span><br><span class="line">	li	t0, CONFIG_SYS_MONITOR_BASE</span><br><span class="line">	sub	t6, a2, t0		# t6 &lt;-- relocation offset</span><br><span class="line"></span><br><span class="line">	la	t3, in_ram</span><br><span class="line">	lw	t2, -12(t3)		# t2 &lt;-- __image_copy_end</span><br><span class="line">	move	t1, a2</span><br><span class="line"></span><br><span class="line">	add	gp, t6			# adjust gp</span><br><span class="line"></span><br><span class="line">	/*</span><br><span class="line">	 * t0 = source address</span><br><span class="line">	 * t1 = target address</span><br><span class="line">	 * t2 = source end address</span><br><span class="line">	 */</span><br><span class="line">1:</span><br><span class="line">	lw	t3, 0(t0)</span><br><span class="line">	sw	t3, 0(t1)</span><br><span class="line">	addu	t0, 4</span><br><span class="line">	blt	t0, t2, 1b</span><br><span class="line">	 addu	t1, 4</span><br><span class="line"></span><br><span class="line">	/* If caches were enabled, we would have to flush them here. */</span><br><span class="line"></span><br><span class="line">	/* flush d-cache */</span><br><span class="line">	li	t0, KSEG0</span><br><span class="line">	or	t1, t0, CONFIG_SYS_DCACHE_SIZE</span><br><span class="line">2:</span><br><span class="line">	cache	INDEX_WRITEBACK_INV_D, 0(t0)</span><br><span class="line">	bne	t0, t1, 2b</span><br><span class="line">	 addi	t0, CONFIG_SYS_CACHELINE_SIZE</span><br><span class="line"></span><br><span class="line">	sync</span><br><span class="line"></span><br><span class="line">	/* flush i-cache */</span><br><span class="line">	li	t0, KSEG0</span><br><span class="line">	or	t1, t0, CONFIG_SYS_ICACHE_SIZE</span><br><span class="line">3:</span><br><span class="line">	cache	INDEX_INVALIDATE_I, 0(t0)</span><br><span class="line">	bne	t0, t1, 3b</span><br><span class="line">	 addi	t0, CONFIG_SYS_CACHELINE_SIZE</span><br><span class="line"></span><br><span class="line">	/* Invalidate BTB */</span><br><span class="line">	mfc0	t0, CP0_CONFIG, 7</span><br><span class="line">	nop</span><br><span class="line">	ori	t0, 2</span><br><span class="line">	mtc0	t0, CP0_CONFIG, 7</span><br><span class="line">	nop</span><br><span class="line"></span><br><span class="line">	/* Jump to where we&apos;ve relocated ourselves */</span><br><span class="line">	addi	t0, a2, in_ram - _start</span><br><span class="line">	jr	t0</span><br><span class="line">	 nop</span><br><span class="line"></span><br><span class="line">	.word	__rel_dyn_end</span><br><span class="line">	.word	__rel_dyn_start</span><br><span class="line">	.word	__image_copy_end</span><br><span class="line">	.word	_GLOBAL_OFFSET_TABLE_</span><br><span class="line">	.word	num_got_entries</span><br><span class="line"></span><br><span class="line">in_ram:</span><br><span class="line">	/*</span><br><span class="line">	 * Now we want to update GOT.</span><br><span class="line">	 *</span><br><span class="line">	 * GOT[0] is reserved. GOT[1] is also reserved for the dynamic object</span><br><span class="line">	 * generated by GNU ld. Skip these reserved entries from relocation.</span><br><span class="line">	 */</span><br><span class="line">	lw	t3, -4(t0)		# t3 &lt;-- num_got_entries</span><br><span class="line">	lw	t4, -8(t0)		# t4 &lt;-- _GLOBAL_OFFSET_TABLE_</span><br><span class="line">	add	t4, t6			# t4 now holds relocated _G_O_T_</span><br><span class="line">	addi	t4, t4, 8		# skipping first two entries</span><br><span class="line">	li	t2, 2</span><br><span class="line">1:</span><br><span class="line">	lw	t1, 0(t4)</span><br><span class="line">	beqz	t1, 2f</span><br><span class="line">	 add	t1, t6</span><br><span class="line">	sw	t1, 0(t4)</span><br><span class="line">2:</span><br><span class="line">	addi	t2, 1</span><br><span class="line">	blt	t2, t3, 1b</span><br><span class="line">	 addi	t4, 4</span><br><span class="line"></span><br><span class="line">	/* Update dynamic relocations */</span><br><span class="line">	lw	t1, -16(t0)		# t1 &lt;-- __rel_dyn_start</span><br><span class="line">	lw	t2, -20(t0)		# t2 &lt;-- __rel_dyn_end</span><br><span class="line"></span><br><span class="line">	b	2f			# skip first reserved entry</span><br><span class="line">	 addi	t1, 8</span><br><span class="line"></span><br><span class="line">1:</span><br><span class="line">	lw	t3, -4(t1)		# t3 &lt;-- relocation info</span><br><span class="line"></span><br><span class="line">	sub	t3, 3</span><br><span class="line">	bnez	t3, 2f			# skip non R_MIPS_REL32 entries</span><br><span class="line">	 nop</span><br><span class="line"></span><br><span class="line">	lw	t3, -8(t1)		# t3 &lt;-- location to fix up in FLASH</span><br><span class="line"></span><br><span class="line">	lw	t4, 0(t3)		# t4 &lt;-- original pointer</span><br><span class="line">	add	t4, t6			# t4 &lt;-- adjusted pointer</span><br><span class="line"></span><br><span class="line">	add	t3, t6			# t3 &lt;-- location to fix up in RAM</span><br><span class="line">	sw	t4, 0(t3)</span><br><span class="line"></span><br><span class="line">2:</span><br><span class="line">	blt	t1, t2, 1b</span><br><span class="line">	 addi	t1, 8			# each rel.dyn entry is 8 bytes</span><br><span class="line"></span><br><span class="line">	/*</span><br><span class="line">	 * Clear BSS</span><br><span class="line">	 *</span><br><span class="line">	 * GOT is now relocated. Thus __bss_start and __bss_end can be</span><br><span class="line">	 * accessed directly via $gp.</span><br><span class="line">	 */</span><br><span class="line">	la	t1, __bss_start		# t1 &lt;-- __bss_start</span><br><span class="line">	la	t2, __bss_end		# t2 &lt;-- __bss_end</span><br><span class="line"></span><br><span class="line">1:</span><br><span class="line">	sw	zero, 0(t1)</span><br><span class="line">	blt	t1, t2, 1b</span><br><span class="line">	 addi	t1, 4</span><br><span class="line"></span><br><span class="line">	move	a0, a1			# a0 &lt;-- gd</span><br><span class="line">	la	t9, board_init_r</span><br><span class="line">	jr	t9</span><br><span class="line">	 move	a1, a2</span><br><span class="line"></span><br><span class="line">	.end	relocate_code</span><br></pre></td></tr></table></figure><ol><li>移动gp指针</li><li>复制代码到RAM中</li><li>刷新一下cache</li><li>跳到RAM代码当中去（in_ram）,in_ram的主要工作是：更新GOT;清空BSS段；最后跳到<code>board_init_r</code>。</li></ol><h5 id="疑问"><a href="#疑问" class="headerlink" title="疑问"></a>疑问</h5><ol><li>如何对函数进行寻址调用</li><li>如何对全局变量进行寻址操作（读写）</li><li>对于全局指针变量中存储的其他变量或函数地址在relocation之后如何操作</li></ol><h5 id="uboot-GOT"><a href="#uboot-GOT" class="headerlink" title="uboot GOT"></a>uboot GOT</h5><blockquote><p>GOTs(global offset tables):是uboot能跳转到不同空间运行的原理.</p></blockquote><p>一个完整可运行的bin文件，link时指定的链接地址，load时的加载地址，运行时的运行地址，这3个地址应该是一致的。但是<code>relocation</code>后运行地址不同于加载地址，特别是链接地址，uboot任何进行函数跳转？？？</p><p>compiler在cc时加入<code>-fpic</code>或<code>-fpie</code>选项，会在目标文件中生成GOT（global offset table），将本文件中需要relocate的值存放在GOT中，函数尾部的Label来存储GOT的offset以及其中变量的offset，变量寻址首先根据尾部Label相对寻址找到GOT地址，以及变量地址在GOT中的位置，从而确定变量地址，这样对于目标文件统一修改GOT中的值，就修改了变量地址的offset，完成了relocation。</p><p>ld时加入-pie选项，就会将GOT并入到<code>rel.dyn</code>段中，uboot在relocate_code中统一根据rel.dyn段修改需要relocation的数值</p><h5 id="划分RAM"><a href="#划分RAM" class="headerlink" title="划分RAM"></a>划分RAM</h5><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">+------------------+</span><br><span class="line">|                  |</span><br><span class="line">|    boot params   |</span><br><span class="line">+------------------+</span><br><span class="line">|                  |</span><br><span class="line">|    Global Data   |</span><br><span class="line">+------------------+</span><br><span class="line">|                  |</span><br><span class="line">|    Board Info    |</span><br><span class="line">+------------------+</span><br><span class="line">|                  |</span><br><span class="line">|   mallco(+env)   |</span><br><span class="line">+------------------+</span><br><span class="line">|                  |</span><br><span class="line">|   uboot code     |</span><br><span class="line">|                  |</span><br><span class="line">|                  |</span><br><span class="line">|                  |</span><br><span class="line">+------------------+</span><br></pre></td></tr></table></figure><h4 id="board-init-r-1"><a href="#board-init-r-1" class="headerlink" title="board_init_r"></a>board_init_r</h4><blockquote><p>This is the next part if the initialization sequence: we are now running from RAM and have a “normal” C environment, i. e. global data can be written, BSS has been cleared, the stack size in not that critical any more, etc.</p></blockquote><p>此时已在DRAM中运行。</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">board_init_r</span><span class="params">(<span class="keyword">gd_t</span> *id, ulong dest_addr)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="meta">#<span class="meta-keyword">ifndef</span> CONFIG_SYS_NO_FLASH</span></span><br><span class="line">	ulong <span class="built_in">size</span>;</span><br><span class="line"><span class="meta">#<span class="meta-keyword">endif</span></span></span><br><span class="line">	<span class="keyword">bd_t</span> *bd;</span><br><span class="line"></span><br><span class="line">	gd = id;</span><br><span class="line">	gd-&gt;flags |= GD_FLG_RELOC;	<span class="comment">/* tell others: relocation done */</span></span><br><span class="line"></span><br><span class="line">	<span class="built_in">printf</span>(<span class="string">"Now running in RAM - U-Boot at: %08lx\n"</span>, dest_addr);</span><br><span class="line"></span><br><span class="line">	gd-&gt;relocaddr = dest_addr;</span><br><span class="line">	gd-&gt;reloc_off = dest_addr - CONFIG_SYS_MONITOR_BASE;</span><br><span class="line"></span><br><span class="line">	monitor_flash_len = image_copy_end() - dest_addr;</span><br><span class="line"></span><br><span class="line">	board_early_init_r();</span><br><span class="line"></span><br><span class="line">	serial_initialize();</span><br><span class="line"></span><br><span class="line">	bd = gd-&gt;bd;</span><br><span class="line"></span><br><span class="line">	<span class="comment">/* The Malloc area is immediately below the monitor copy in DRAM */</span></span><br><span class="line">	mem_malloc_init(CONFIG_SYS_MONITOR_BASE + gd-&gt;reloc_off -</span><br><span class="line">			TOTAL_MALLOC_LEN, TOTAL_MALLOC_LEN);</span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">ifndef</span> CONFIG_SYS_NO_FLASH</span></span><br><span class="line">	<span class="comment">/* configure available FLASH banks */</span></span><br><span class="line">	<span class="built_in">size</span> = flash_init();</span><br><span class="line">	display_flash_config(<span class="built_in">size</span>);</span><br><span class="line">	bd-&gt;bi_flashstart = CONFIG_SYS_FLASH_BASE;</span><br><span class="line">	bd-&gt;bi_flashsize = <span class="built_in">size</span>;</span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">if</span> CONFIG_SYS_MONITOR_BASE == CONFIG_SYS_FLASH_BASE</span></span><br><span class="line">	bd-&gt;bi_flashoffset = monitor_flash_len;	<span class="comment">/* reserved area for U-Boot */</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">else</span></span></span><br><span class="line">	bd-&gt;bi_flashoffset = <span class="number">0</span>;</span><br><span class="line"><span class="meta">#<span class="meta-keyword">endif</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">else</span></span></span><br><span class="line">	bd-&gt;bi_flashstart = <span class="number">0</span>;</span><br><span class="line">	bd-&gt;bi_flashsize = <span class="number">0</span>;</span><br><span class="line">	bd-&gt;bi_flashoffset = <span class="number">0</span>;</span><br><span class="line"><span class="meta">#<span class="meta-keyword">endif</span></span></span><br><span class="line">	...</span><br><span class="line"><span class="meta">#<span class="meta-keyword">ifdef</span> CONFIG_GENERIC_MMC</span></span><br><span class="line">	<span class="built_in">puts</span>(<span class="string">"MMC:   "</span>);</span><br><span class="line">	mmc_initialize(bd);</span><br><span class="line"><span class="meta">#<span class="meta-keyword">endif</span></span></span><br><span class="line"></span><br><span class="line">	<span class="comment">/* relocate environment function pointers etc. */</span></span><br><span class="line">	env_relocate();</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">/*leave this here (after malloc(), environment and PCI are working)*/</span></span><br><span class="line">	<span class="comment">/* Initialize stdio devices */</span></span><br><span class="line">	stdio_init();</span><br><span class="line"></span><br><span class="line">	jumptable_init();</span><br><span class="line"></span><br><span class="line">	<span class="comment">/* Initialize the console (after the relocation and devices init) */</span></span><br><span class="line">	console_init_r();</span><br><span class="line"></span><br><span class="line">	<span class="comment">/* Initialize from environment */</span></span><br><span class="line">	load_addr = getenv_ulong(<span class="string">"loadaddr"</span>, <span class="number">16</span>, load_addr);</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">ifdef</span> CONFIG_USB_GADGET</span></span><br><span class="line"><span class="function"><span class="keyword">extern</span> <span class="keyword">void</span> <span class="title">board_usb_init</span><span class="params">(<span class="keyword">void</span>)</span></span>;</span><br><span class="line">	board_usb_init();</span><br><span class="line"><span class="meta">#<span class="meta-keyword">endif</span></span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">if</span> defined(CONFIG_MISC_INIT_R)</span></span><br><span class="line">	<span class="comment">/* miscellaneous platform dependent initialisations */</span></span><br><span class="line">	misc_init_r();</span><br><span class="line"><span class="meta">#<span class="meta-keyword">endif</span></span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">ifdef</span> CONFIG_BITBANGMII</span></span><br><span class="line">	bb_miiphy_init();</span><br><span class="line"><span class="meta">#<span class="meta-keyword">endif</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">if</span> defined(CONFIG_CMD_NET)</span></span><br><span class="line">	<span class="built_in">puts</span>(<span class="string">"Net:   "</span>);</span><br><span class="line">	eth_initialize(gd-&gt;bd);</span><br><span class="line"><span class="meta">#<span class="meta-keyword">endif</span></span></span><br><span class="line"></span><br><span class="line">	<span class="comment">/* main_loop() can return to retry autoboot, if so just run it again. */</span></span><br><span class="line">	<span class="keyword">for</span> (;;)</span><br><span class="line">		main_loop();</span><br><span class="line">	<span class="comment">/*NOTREACHED - no way out of command loop except booting*/</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><ol><li>初始化串口</li><li>初始化系统内存分配函数</li><li>如果使用MMC存储介质，初始化MMC设备</li><li>初始化环境变量的指针,将 env_ptr 指针及其指向的地址初始化，用来存放环境变量结构体，然后将 flash 中的环境变量拷贝到内存中。</li><li>初始化sdio设备</li><li>初始化网络设备</li><li>进去命令循环（即整个boot的工作循环），接受用户从串口输入的命令，然后进行相应的工作</li></ol><h3 id="main-loop"><a href="#main-loop" class="headerlink" title="main_loop"></a>main_loop</h3><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">main_loop</span><span class="params">(<span class="keyword">void</span>)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	...</span><br><span class="line">	bootstage_mark_name(BOOTSTAGE_ID_MAIN_LOOP, <span class="string">"main_loop"</span>);</span><br><span class="line"></span><br><span class="line">	<span class="comment">/*刷新LCD*/</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">if</span> defined(CONFIG_UPDATE_TFTP)</span></span><br><span class="line">	update_tftp(<span class="number">0U</span>L);</span><br><span class="line"><span class="meta">#<span class="meta-keyword">endif</span> <span class="comment">/* CONFIG_UPDATE_TFTP */</span></span></span><br><span class="line"><span class="comment">/*从环境变量中取得bootdelay 内核等待延时*/</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">ifdef</span> CONFIG_BOOTDELAY</span></span><br><span class="line">	process_boot_delay();</span><br><span class="line"><span class="meta">#<span class="meta-keyword">endif</span></span></span><br><span class="line">	<span class="comment">/*</span></span><br><span class="line"><span class="comment">	 * Main Loop for Monitor Command Processing</span></span><br><span class="line"><span class="comment">	 */</span></span><br><span class="line">	<span class="keyword">for</span> (;;) &#123;</span><br><span class="line">		len = readline (CONFIG_SYS_PROMPT);</span><br><span class="line"></span><br><span class="line">		flag = <span class="number">0</span>;	<span class="comment">/* assume no special flags for now */</span></span><br><span class="line">		<span class="keyword">if</span> (len &gt; <span class="number">0</span>)</span><br><span class="line">			<span class="built_in">strcpy</span> (lastcommand, console_buffer);</span><br><span class="line">		<span class="keyword">else</span> <span class="keyword">if</span> (len == <span class="number">0</span>)</span><br><span class="line">			flag |= CMD_FLAG_REPEAT;</span><br><span class="line"></span><br><span class="line">		<span class="keyword">if</span> (len == <span class="number">-1</span>)</span><br><span class="line">			<span class="built_in">puts</span> (<span class="string">"&lt;INTERRUPT&gt;\n"</span>);</span><br><span class="line">		<span class="keyword">else</span></span><br><span class="line">			rc = run_command(lastcommand, flag); <span class="comment">//执行命令</span></span><br><span class="line"></span><br><span class="line">		<span class="keyword">if</span> (rc &lt;= <span class="number">0</span>) &#123;</span><br><span class="line">			<span class="comment">/* invalid command or not repeatable, forget it */</span></span><br><span class="line">			lastcommand[<span class="number">0</span>] = <span class="number">0</span>;</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><blockquote><p>file:common/main.c</p></blockquote><h3 id="do-bootm"><a href="#do-bootm" class="headerlink" title="do_bootm"></a>do_bootm</h3><p>将内核解压缩，然后调用do_bootm_linux引导内核</p><h3 id="do-bootm-linux"><a href="#do-bootm-linux" class="headerlink" title="do_bootm_linux"></a>do_bootm_linux</h3><p>启动内核</p><h2 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h2><ol><li><a href="http://blog.csdn.net/skyflying2012/article/details/37660265" target="_blank" rel="noopener">uboot的relocation原理详细分析</a></li></ol></div><div class="popular-posts-header">相关文章</div><ul class="popular-posts"><li class="popular-posts-item"><div class="popular-posts-title"><a href="/post/36419.html" rel="bookmark">Cortex-A8平台实验</a></div></li></ul><div class="post-widgets"><div id="needsharebutton-postbottom"><span class="btn"><i class="fa fa-share-alt" aria-hidden="true"></i></span></div></div><div><div style="text-align:center;color:#ccc;font-size:14px">-------------本文结束<i class="fa fa-paw"></i>感谢您的阅读-------------</div><div style="text-align:center;color:#ccc;font-size:16px"><script type="text/javascript" src="https://api.imjad.cn/hitokoto/?cat=&charset=utf-8&length=50&encode=js&fun=sync&source="></script><div id="hitokoto"><script>hitokoto()</script></div></div><div class="reward-container"><div></div> <button disable="enable" onclick="var qr = document.getElementById(&quot;qr&quot;); qr.style.display = (qr.style.display === 'none') ? 'block' : 'none';"> 打赏</button><div id="qr" style="display:none"><div style="display:inline-block"> <img src="/images/alipay.jpg" alt="Winddoing 支付宝"><p>支付宝</p></div></div></div><div><ul class="post-copyright"><li class="post-copyright-author"> <strong>本文作者：</strong> Winddoing</li><li class="post-copyright-link"> <strong>本文链接：</strong> <a href="http://winddoing.github.io/post/47503.html" title="uboot">http://winddoing.github.io/post/47503.html</a></li><li class="post-copyright-statement"> <strong>作者声明：</strong> 本博文为个人笔记, 由于个人能力有限，难免出现错误，欢迎大家批评指正。</li><li class="post-copyright-license"> <strong>版权声明：</strong> 本博客所有文章除特别声明外，均采用<a href="https://creativecommons.org/licenses/by-nc-sa/4.0/" rel="noopener" target="_blank"><i class="fa fa-fw fa-creative-commons"></i> BY-NC-SA</a> 许可协议。转载请注明出处！</li></ul></div><footer class="post-footer"><div class="post-tags"><a href="/tags/uboot/" rel="tag"><i class="fa fa-tag"></i> uboot</a></div><div class="post-nav"><div class="post-nav-item"><a href="/post/16306.html" rel="prev" title="Hung Task"><i class="fa fa-chevron-left"></i> Hung Task</a></div><div class="post-nav-item"> <a href="/post/40876.html" rel="next" title="tmux">tmux<i class="fa fa-chevron-right"></i></a></div></div></footer></div></article></div></div><div class="comments"><div id="lv-container" data-id="city" data-uid="MTAyMC8yOTM5OC81OTY2"></div></div><script>
  window.addEventListener('tabs:register', () => {
    let activeClass = CONFIG.comments.activeClass;
    if (CONFIG.comments.storage) {
      activeClass = localStorage.getItem('comments_active') || activeClass;
    }
    if (activeClass) {
      let activeTab = document.querySelector(`a[href="#comment-${activeClass}"]`);
      if (activeTab) {
        activeTab.click();
      }
    }
  });
  if (CONFIG.comments.storage) {
    window.addEventListener('tabs:click', event => {
      if (!event.target.matches('.tabs-comment .tab-content .tab-pane')) return;
      let commentClass = event.target.classList[1];
      localStorage.setItem('comments_active', commentClass);
    });
  }
</script></div><div class="toggle sidebar-toggle"><span class="toggle-line toggle-line-first"></span><span class="toggle-line toggle-line-middle"></span><span class="toggle-line toggle-line-last"></span></div><aside class="sidebar"><div class="sidebar-inner"><ul class="sidebar-nav motion-element"><li class="sidebar-nav-toc"> 文章目录</li><li class="sidebar-nav-overview"> 站点概览</li></ul><div class="post-toc-wrap sidebar-panel"><div class="post-toc motion-element"><ol class="nav"><li class="nav-item nav-level-2"><a class="nav-link" href="#目的"><span class="nav-number">1.</span> <span class="nav-text">目的</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#流程"><span class="nav-number">2.</span> <span class="nav-text">流程:</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#SPL"><span class="nav-number">3.</span> <span class="nav-text">SPL</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#u-boot-spl-lds"><span class="nav-number">3.1.</span> <span class="nav-text">u-boot-spl.lds</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#start-S"><span class="nav-number">3.2.</span> <span class="nav-text">start.S</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#soc-c"><span class="nav-number">3.3.</span> <span class="nav-text">soc.c</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#数据结构"><span class="nav-number">3.3.1.</span> <span class="nav-text">数据结构</span></a><ol class="nav-child"><li class="nav-item nav-level-5"><a class="nav-link" href="#bd-t"><span class="nav-number">3.3.1.1.</span> <span class="nav-text">bd_t</span></a></li><li class="nav-item nav-level-5"><a class="nav-link" href="#gd-t"><span class="nav-number">3.3.1.2.</span> <span class="nav-text">gd_t</span></a></li></ol></li><li class="nav-item nav-level-4"><a class="nav-link" href="#board-init-f"><span class="nav-number">3.3.2.</span> <span class="nav-text">board_init_f</span></a><ol class="nav-child"><li class="nav-item nav-level-5"><a class="nav-link" href="#ginfo"><span class="nav-number">3.3.2.1.</span> <span class="nav-text">ginfo</span></a></li><li class="nav-item nav-level-5"><a class="nav-link" href="#为什么要清除BSS段？"><span class="nav-number">3.3.2.2.</span> <span class="nav-text">为什么要清除BSS段？</span></a></li></ol></li><li class="nav-item nav-level-4"><a class="nav-link" href="#board-init-r"><span class="nav-number">3.3.3.</span> <span class="nav-text">board_init_r</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#执行C代码所必需的条件或者环境？"><span class="nav-number">3.4.</span> <span class="nav-text">执行C代码所必需的条件或者环境？</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#SPL执行阶段其栈空间的位置？"><span class="nav-number">3.5.</span> <span class="nav-text">SPL执行阶段其栈空间的位置？</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#uboot"><span class="nav-number">4.</span> <span class="nav-text">uboot</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#u-boot-lds"><span class="nav-number">4.1.</span> <span class="nav-text">u-boot.lds</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#start-S-1"><span class="nav-number">4.2.</span> <span class="nav-text">start.S</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#为什么不直接跳转，而使用jr"><span class="nav-number">4.2.1.</span> <span class="nav-text">为什么不直接跳转，而使用jr</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#board-c"><span class="nav-number">4.3.</span> <span class="nav-text">board.c</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#uboot内存布局："><span class="nav-number">4.3.1.</span> <span class="nav-text">uboot内存布局：</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#board-init-f-1"><span class="nav-number">4.3.2.</span> <span class="nav-text">board_init_f</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#relocate-code"><span class="nav-number">4.3.3.</span> <span class="nav-text">relocate_code</span></a><ol class="nav-child"><li class="nav-item nav-level-5"><a class="nav-link" href="#疑问"><span class="nav-number">4.3.3.1.</span> <span class="nav-text">疑问</span></a></li><li class="nav-item nav-level-5"><a class="nav-link" href="#uboot-GOT"><span class="nav-number">4.3.3.2.</span> <span class="nav-text">uboot GOT</span></a></li><li class="nav-item nav-level-5"><a class="nav-link" href="#划分RAM"><span class="nav-number">4.3.3.3.</span> <span class="nav-text">划分RAM</span></a></li></ol></li><li class="nav-item nav-level-4"><a class="nav-link" href="#board-init-r-1"><span class="nav-number">4.3.4.</span> <span class="nav-text">board_init_r</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#main-loop"><span class="nav-number">4.4.</span> <span class="nav-text">main_loop</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#do-bootm"><span class="nav-number">4.5.</span> <span class="nav-text">do_bootm</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#do-bootm-linux"><span class="nav-number">4.6.</span> <span class="nav-text">do_bootm_linux</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#参考"><span class="nav-number">5.</span> <span class="nav-text">参考</span></a></li></ol></div></div><div class="site-overview-wrap sidebar-panel"><div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person"> <img class="site-author-image" itemprop="image" alt="Winddoing" src="/images/Winddoing.jpg"><p class="site-author-name" itemprop="name">Winddoing</p><div class="site-description" itemprop="description">失败缘于忽视细处，成功始于重视小事。</div></div><div class="site-state-wrap motion-element"><nav class="site-state"><div class="site-state-item site-state-posts"> <a href="/archives/"><span class="site-state-item-count">248</span> <span class="site-state-item-name">日志</span></a></div><div class="site-state-item site-state-categories"> <a href="/categories/"><span class="site-state-item-count">57</span> <span class="site-state-item-name">分类</span></a></div><div class="site-state-item site-state-tags"> <a href="/tags/"><span class="site-state-item-count">214</span> <span class="site-state-item-name">标签</span></a></div></nav></div><div class="links-of-author motion-element"><span class="links-of-author-item"><a href="https://github.com/Winddoing" title="GitHub → https:&#x2F;&#x2F;github.com&#x2F;Winddoing" rel="noopener" target="_blank"><i class="fa fa-fw fa-github"></i> GitHub</a></span><span class="links-of-author-item"><a href="https://gitee.com/winddoing" title="Gitee → https:&#x2F;&#x2F;gitee.com&#x2F;winddoing" rel="noopener" target="_blank"><i class="fa fa-fw fa-codiepie"></i> Gitee</a></span><span class="links-of-author-item"><a href="mailto:winddoing@sina.cn" title="E-Mail → mailto:winddoing@sina.cn" rel="noopener" target="_blank"><i class="fa fa-fw fa-envelope"></i> E-Mail</a></span><span class="links-of-author-item"><a href="https://stackoverflow.com/users/9567361/winddoing" title="StackOverflow → https:&#x2F;&#x2F;stackoverflow.com&#x2F;users&#x2F;9567361&#x2F;winddoing" rel="noopener" target="_blank"><i class="fa fa-fw fa-stack-overflow"></i> StackOverflow</a></span><span class="links-of-author-item"><a href="https://travis-ci.org/Winddoing/Winddoing.github.io" title="Travis CI → https:&#x2F;&#x2F;travis-ci.org&#x2F;Winddoing&#x2F;Winddoing.github.io" rel="noopener" target="_blank"><i class="fa fa-fw fa-terminal"></i> Travis CI</a></span></div><div class="cc-license motion-element" itemprop="license"> <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/" class="cc-opacity" rel="noopener" target="_blank"><img src="/images/cc-by-nc-sa.svg" alt="Creative Commons"></a></div><div class="links-of-blogroll motion-element"><div class="links-of-blogroll-title"><i class="fa fa-fw fa-link"></i> Links</div><ul class="links-of-blogroll-list"><li class="links-of-blogroll-item"> <a href="https://winddoing.gitbooks.io/embedded_notes/content/" title="https:&#x2F;&#x2F;winddoing.gitbooks.io&#x2F;embedded_notes&#x2F;content&#x2F;" rel="noopener" target="_blank">嵌入式相关</a></li><li class="links-of-blogroll-item"> <a href="http://blog.csdn.net/sdreamq" title="http:&#x2F;&#x2F;blog.csdn.net&#x2F;sdreamq" rel="noopener" target="_blank">CSDN</a></li><li class="links-of-blogroll-item"> <a href="http://www.wowotech.net/" title="http:&#x2F;&#x2F;www.wowotech.net&#x2F;" rel="noopener" target="_blank">蜗窝科技</a></li><li class="links-of-blogroll-item"> <a href="https://blog.csdn.net/xiongxianze" title="https:&#x2F;&#x2F;blog.csdn.net&#x2F;xiongxianze" rel="noopener" target="_blank">xiongxianze</a></li></ul></div><div id="days"></div><script>function show_date_time(){window.setTimeout("show_date_time()",1e3),BirthDay=new Date("02/26/2014 15:00:00"),today=new Date,timeold=today.getTime()-BirthDay.getTime(),sectimeold=timeold/1e3,secondsold=Math.floor(sectimeold),msPerDay=864e5,e_daysold=timeold/msPerDay,daysold=Math.floor(e_daysold),e_hrsold=24*(e_daysold-daysold),hrsold=setzero(Math.floor(e_hrsold)),e_minsold=60*(e_hrsold-hrsold),minsold=setzero(Math.floor(60*(e_hrsold-hrsold))),seconds=setzero(Math.floor(60*(e_minsold-minsold))),document.getElementById("days").innerHTML="已运行"+daysold+"天"+hrsold+"小时"+minsold+"分"+seconds+"秒"}function setzero(e){return e<10&&(e="0"+e),e}show_date_time()</script></div></div></aside><div id="sidebar-dimmer"></div></div></main><footer class="footer"><div class="footer-inner"><div class="copyright"> &copy; 2014 – <span itemprop="copyrightYear">2020</span><span class="with-love" id="heart"><i class="fa fa-heartbeat"></i></span> <span class="author" itemprop="copyrightHolder">Winddoing</span> <span class="post-meta-divider">|</span><span class="post-meta-item-icon"><i class="fa fa-area-chart"></i></span> <span title="站点总字数">652k</span> <span class="post-meta-divider">|</span><span class="post-meta-item-icon"><i class="fa fa-coffee"></i></span> <span title="站点阅读时长">9:53</span></div><div class="powered-by">由 <a href="https://hexo.io/" class="theme-link" rel="noopener" target="_blank">Hexo</a> 强力驱动 v3.9.0</div> <span class="post-meta-divider">|</span><div class="theme-info">主题 – <a href="https://mist.theme-next.org/" class="theme-link" rel="noopener" target="_blank">NexT.Mist</a> v7.7.0</div><div class="busuanzi-count"><script async src="https://busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script><span class="post-meta-item" id="busuanzi_container_site_uv" style="display:none"><span class="post-meta-item-icon"><i class="fa fa-user"></i></span><span class="site-uv" title="总访客量"><span id="busuanzi_value_site_uv"></span></span></span> <span class="post-meta-divider">|</span><span class="post-meta-item" id="busuanzi_container_site_pv" style="display:none"><span class="post-meta-item-icon"><i class="fa fa-eye"></i></span><span class="site-pv" title="总访问量"><span id="busuanzi_value_site_pv"></span></span></span></div><div style="display:inline"><script type="text/javascript">var cnzz_protocol="https:"==document.location.protocol?" https://":" http://";document.write(unescape("%3Cspan id='cnzz_stat_icon_1254703532'%3E%3C/span%3E%3Cscript src='"+cnzz_protocol+"s95.cnzz.com/z_stat.php%3Fid%3D1254703532%26show%3Dpic' type='text/javascript'%3E%3C/script%3E"))</script></div><script>
  function leancloudSelector(url) {
    url = encodeURI(url);
    return document.getElementById(url).querySelector('.leancloud-visitors-count');
  }
  if (CONFIG.page.isPost) {
    function addCount(Counter) {
      var visitors = document.querySelector('.leancloud_visitors');
      var url = decodeURI(visitors.getAttribute('id'));
      var title = visitors.getAttribute('data-flag-title');

      Counter('get', `/classes/Counter?where=${JSON.stringify({ url })}`)
        .then(response => response.json())
        .then(({ results }) => {
          if (results.length > 0) {
            var counter = results[0];
            Counter('put', '/classes/Counter/' + counter.objectId, { time: { '__op': 'Increment', 'amount': 1 } })
              .then(response => response.json())
              .then(() => {
                leancloudSelector(url).innerText = counter.time + 1;
              })
              .catch(error => {
                console.error('Failed to save visitor count', error);
              })
          } else {
              Counter('post', '/classes/Counter', { title: title, url: url, time: 1 })
                .then(response => response.json())
                .then(() => {
                  leancloudSelector(url).innerText = 1;
                })
                .catch(error => {
                  console.error('Failed to create', error);
                });
          }
        })
        .catch(error => {
          console.error('LeanCloud Counter Error', error);
        });
    }
  } else {
    function showTime(Counter) {
      var visitors = document.querySelectorAll('.leancloud_visitors');
      var entries = [...visitors].map(element => {
        return decodeURI(element.getAttribute('id'));
      });

      Counter('get', `/classes/Counter?where=${JSON.stringify({ url: { '$in': entries } })}`)
        .then(response => response.json())
        .then(({ results }) => {
          if (results.length === 0) {
            document.querySelectorAll('.leancloud_visitors .leancloud-visitors-count').forEach(element => {
              element.innerText = 0;
            });
            return;
          }
          for (let item of results) {
            let { url, time } = item;
            leancloudSelector(url).innerText = time;
          }
          for (let url of entries) {
            var element = leancloudSelector(url);
            if (element.innerText == '') {
              element.innerText = 0;
            }
          }
        })
        .catch(error => {
          console.error('LeanCloud Counter Error', error);
        });
    }
  }

  fetch('https://app-router.leancloud.cn/2/route?appId=Q8qpjA3fOO7FEUBqcmcQFptF-gzGzoHsz')
    .then(response => response.json())
    .then(({ api_server }) => {
      var Counter = (method, url, data) => {
        return fetch(`https://${api_server}/1.1${url}`, {
          method: method,
          headers: {
            'X-LC-Id': 'Q8qpjA3fOO7FEUBqcmcQFptF-gzGzoHsz',
            'X-LC-Key': 'tgUTq5bX3fVmn916EMRe65eJ',
            'Content-Type': 'application/json',
          },
          body: JSON.stringify(data)
        });
      };
      if (CONFIG.page.isPost) {
        if (CONFIG.hostname !== location.hostname) return;
        addCount(Counter);
      } else if (document.querySelectorAll('.post-title-link').length >= 1) {
        showTime(Counter);
      }
    });
  </script></div></footer></div><script src="/lib/anime.min.js"></script><script src="/lib/velocity/velocity.min.js"></script><script src="/lib/velocity/velocity.ui.min.js"></script><script src="/js/utils.js"></script><script src="/js/motion.js"></script><script src="/js/schemes/muse.js"></script><script src="/js/next-boot.js"></script><script>!function(){var t=document.createElement("script"),e=window.location.protocol.split(":")[0];t.src="https"===e?"https://zz.bdstatic.com/linksubmit/push.js":"http://push.zhanzhang.baidu.com/push.js";var s=document.getElementsByTagName("script")[0];s.parentNode.insertBefore(t,s)}()</script><script src="/js/local-search.js"></script><script>
if (document.querySelectorAll('pre.mermaid').length) {
  NexT.utils.getScript('//cdn.jsdelivr.net/npm/mermaid@8/dist/mermaid.min.js', () => {
    mermaid.initialize({
      theme: 'forest',
      logLevel: 3,
      flowchart: { curve: 'linear' },
      gantt: { axisFormat: '%m/%d/%Y' },
      sequence: { actorMargin: 50 }
    });
  }, window.mermaid);
}
</script><script src="//cdn.jsdelivr.net/gh/theme-next/theme-next-needmoreshare2@1/needsharebutton.min.js"></script><script>pbOptions={iconStyle:"default",boxForm:"horizontal",position:"bottomCenter",networks:"Weibo,Wechat,QQZone,Twitter,Facebook,Evernote"},new needShareButton("#needsharebutton-postbottom",pbOptions)</script><script>
NexT.utils.loadComments(document.querySelector('#lv-container'), () => {
  window.livereOptions = {
    refer: location.pathname.replace(CONFIG.root, '').replace('index.html', '')
  };
  (function(d, s) {
    var j, e = d.getElementsByTagName(s)[0];
    if (typeof LivereTower === 'function') { return; }
    j = d.createElement(s);
    j.src = 'https://cdn-city.livere.com/js/embed.dist.js';
    j.async = true;
    e.parentNode.insertBefore(j, e);
  })(document, 'script');
});
</script></body></html>